﻿using MaterialSkin.Controls;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using static System.Windows.Forms.VisualStyles.VisualStyleElement;
using System.Xml.Linq;
using static System.Windows.Forms.VisualStyles.VisualStyleElement.Button;
using System.Reflection.Emit;
using System.Text.RegularExpressions;
using ScottPlot;
using ScottPlot.WinForms;
using ScottPlot.DataGenerators;
using ScottPlot.AxisPanels;
using ScottPlot.Colormaps;
using MaterialSkin;



namespace WindowsFormsApp2
{
    public partial class Form1 : MaterialForm
    {
        public string Title => "Data Logger";
        public string Description => "Plots live streaming data as a growing line plot.";

        //主题相关
        private MaterialSkinManager materialSkinManager;


        //串口相关
        public String str;
        public float torque;

        //波形图相关
        readonly FormsPlot myPlot = new FormsPlot() { Dock = DockStyle.Fill };
        readonly System.Windows.Forms.Timer AddNewDataTimer = new Timer() { Interval = 10, Enabled = true };
        readonly System.Windows.Forms.Timer UpdatePlotTimer = new Timer() { Interval = 50, Enabled = true };

        ScottPlot.Plottables.DataLogger Logger1;
        ScottPlot.Plottables.DataLogger Logger2;

        //显示波形
        Boolean waveEnableFlag;

        //时间
        private DateTime current_time = new DateTime();    //为了避免在接收处理函数中反复调用，依然声明为一个全局变量


        public Form1()
        {
            InitializeComponent();
            //增加串口事件处理函数
            serialPort1.DataReceived += new SerialDataReceivedEventHandler(PortDataReceivedEvent);
            //建议关一下线程的检查
            System.Windows.Forms.Control.CheckForIllegalCrossThreadCalls = false;
            //支持中文解码
            serialPort1.Encoding = Encoding.GetEncoding("GB2312");

            //自动搜索串口
            GetComList();

            //注册按钮
            btnClick();

            formPlotInit();

            //主题初始化
            themeInit();
        }

        private void materialButton1_Click(object sender, EventArgs e)
        {

        }

        private void tabPage1_Click(object sender, EventArgs e)
        {

        }

        private void materialRadioButton4_CheckedChanged(object sender, EventArgs e)
        {

        }

        /// <summary>
        /// 类似串口中断调用
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="args"></param>
        private void PortDataReceivedEvent(object sender, SerialDataReceivedEventArgs args)
        {
            //byte Data = (byte)serialPort1.ReadByte();

            int len = serialPort1.BytesToRead;//获取可以读取的字节数

            byte[] buff = new byte[len];//创建缓存数据数组

            serialPort1.Read(buff, 0, len);//把数据读取到buff数组

            str = Encoding.ASCII.GetString(buff);
            if (str.Contains(":"))//包含冒号的话
            {
                string[] sArray = str.Split(new char[2] { ':', ',' });//分开数据
                if (sArray[0] == "torque") //头为torque
                {
                    torque = float.Parse(sArray[1]);
                    Logger1.Add(torque);
                    torqueLable.Text = Convert.ToString(torque);
                }

            }

            showTimeLable();
            if (rx_hex.Checked)//是否勾选十六进制显示
            {
                rx_textBox.AppendText(BitConverter.ToString(buff).Replace('-', ' ') + '\n');//转成十六进制显示
            }
            else
            {
                rx_textBox.AppendText(Encoding.ASCII.GetString(buff));//转成ASCII码显示
                //rx_textBox.AppendText("\n");
            }
        }

        /// <summary>
        /// 自动获取串口的端口号
        /// </summary>
        /// <returns></returns>
        public void GetComList()
        {
            string[] names = SerialPort.GetPortNames();
            serialComboBox.Items.Clear();
            for (int i = 0; i < names.Length; i++)
            {
                serialComboBox.Items.Add(names[i]);
                serialComboBox.SelectedIndex = 0;
            }
        }

        private void searchSerialPortButton_Click(object sender, EventArgs e)
        {
            //搜索串口
            GetComList();
        }

        private void submitButton_Click(object sender, EventArgs e)
        {
            byte[] temp = new byte[1];
            current_time = System.DateTime.Now;     //获取当前时间

            showTimeLable();
            try
            {
                //首先判断串口是否开启
                if (serialPort1.IsOpen)
                {
                    int num = 0;   //获取本次发送字节数
                                   //串口处于开启状态，将发送区文本发送

                    //判断发送模式
                    if (tx_hex.Checked)
                    {
                        //以HEX模式发送
                        //首先需要用正则表达式将用户输入字符中的十六进制字符匹配出来
                        string buf = tx_textBox.Text;
                        string pattern = @"\s";
                        string replacement = "";
                        Regex rgx = new Regex(pattern);
                        string send_data = rgx.Replace(buf, replacement);

                        //不发送新行
                        num = (send_data.Length - send_data.Length % 2) / 2;
                        for (int i = 0; i < num; i++)
                        {
                            temp[0] = Convert.ToByte(send_data.Substring(i * 2, 2), 16);
                            serialPort1.Write(temp, 0, 1);  //循环发送
                            rx_textBox.AppendText(send_data.Substring(i * 2, 2));
                            rx_textBox.AppendText(" ");
                        }
                        //如果用户输入的字符是奇数，则单独处理
                        if (send_data.Length % 2 != 0)
                        {
                            temp[0] = Convert.ToByte(send_data.Substring(tx_textBox.Text.Length - 1, 1), 16);
                            serialPort1.Write(temp, 0, 1);
                            num++;

                            rx_textBox.AppendText(send_data.Substring(tx_textBox.Text.Length - 1, 1));
                            rx_textBox.AppendText(" ");
                        }

                    }
                    else
                    {
                        //不发送新行
                        serialPort1.Write(tx_textBox.Text);
                        num = tx_textBox.Text.Length;
                        rx_textBox.AppendText(tx_textBox.Text);
                    }
                    //rx_textBox.AppendText("\r\n");
                    //send_count += num;      //计数变量累加
                }
            }
            catch (Exception ex)
            {
                serialPort1.Close();
            }
        }

        private void connectButton_Click(object sender, EventArgs e)
        {
            try
            {
                if (!serialPort1.IsOpen)
                {
                    serialPort1.PortName = serialComboBox.Text;     //串口号
                    serialPort1.BaudRate = int.Parse(baudRateComboBox.Text);   //设置波特率
                    serialPort1.Open();
                    connectButton.Text = "关闭串口";
                    connectButton.UseAccentColor = true;
                    submitButton.Enabled = true;
                }
                else
                {
                    serialPort1.Close();
                    connectButton.Text = "打开串口";
                    connectButton.UseAccentColor = false;
                    submitButton.Enabled = false;
                }
            }
            catch
            {
                MessageBox.Show("串口出问题了！");//消息
            }


        }

        private void materialButton2_Click(object sender, EventArgs e)
        {
            rx_textBox.Text = "";
        }


        private void showTimeLable()
        {
            if (showTimelCheckbox.Checked)
            {
                //添加行
                rx_textBox.AppendText("\r\n");
                //显示时间
                current_time = System.DateTime.Now;     //获取当前时间
                rx_textBox.AppendText(current_time.ToString("[HH:mm:ss]"));
            }
        }

        private void formPlotInit()
        {
            // Add the FormsPlot to the panel
            panel1.Controls.Add(myPlot);

            // disable interactivity by default
            //FormsPlot1.Interaction.Disable();

            // create two loggers and add them to the plot
            Logger1 = myPlot.Plot.Add.DataLogger();
            Logger2 = myPlot.Plot.Add.DataLogger();

            // use the right axis (already there by default) for the first logger
            RightAxis axis1 = (RightAxis)myPlot.Plot.Axes.Right;
            Logger1.Axes.YAxis = axis1;
            axis1.Color(Logger1.Color);

            // create and add a secondary right axis to use for the other logger
            RightAxis axis2 = myPlot.Plot.Axes.AddRightAxis();
            Logger2.Axes.YAxis = axis2;
            axis2.Color(Logger2.Color);

            AddNewDataTimer.Tick += (s, e) =>
            {
                int count = 5;
                //Logger1.Add(1);
                //Logger2.Add(1);
            };

            UpdatePlotTimer.Tick += (s, e) =>
            {
                if (Logger1.HasNewData || Logger2.HasNewData)
                    myPlot.Refresh();
            };

            // wire our buttons to change the view modes of each logger
            btnFull.Click += (s, e) => { Logger1.ViewFull(); Logger2.ViewFull(); };
            btnJump.Click += (s, e) => { Logger1.ViewJump(); Logger2.ViewJump(); };
            btnSlide.Click += (s, e) => { Logger1.ViewSlide(); Logger2.ViewSlide(); };
        }

        /// <summary>
        /// 一些按钮的操作
        /// </summary>
        private void btnClick()
        {
            byte[] command = new byte[1];
            // wire our buttons to change the view modes of each logger
            initPositionMode.Click += (s, e) =>
            {
                command[0] = 0xFE;
                serialPort1.Write(command, 0, 1);
            };
            addPosition.Click += (s, e) =>
            {
                command[0] = 0x0A;
                serialPort1.Write(command, 0, 1);
            };
            delPosition.Click += (s, e) =>
            {
                command[0] = 0x0B;
                serialPort1.Write(command, 0, 1);
            };
            setZero.Click += (s, e) =>
            {
                command[0] = 0x0C;
                serialPort1.Write(command, 0, 1);
            };


            waveEnable.Click += (s, e) =>
            {
                if (waveEnable.Text == "停止")
                {
                    waveEnable.Text = "开始";
                    waveEnable.UseAccentColor = false;
                    waveEnableFlag = false;
                }
                else
                {
                    waveEnable.Text = "停止";
                    waveEnable.UseAccentColor = true;
                    waveEnableFlag = true;
                }

            };
        }

        private void motorEnable_Click(object sender, EventArgs e)
        {
            byte[] command = new byte[1];
            if (motorEnable.Text == "电机使能")
            {
                command[0] = 0xA1;
                serialPort1.Write(command, 0, 1);
                motorEnable.Text = "电机失能";
                motorEnable.UseAccentColor = true;
            }
            else
            {
                command[0] = 0xA2;
                serialPort1.Write(command, 0, 1);
                motorEnable.Text = "电机使能";
                motorEnable.UseAccentColor = false;
            }
        }


        /// <summary>
        /// 主题初始化
        /// </summary>
        private void themeInit()
        {
            materialSkinManager = MaterialSkinManager.Instance;
            materialSkinManager.EnforceBackcolorOnAllComponents = true;
            materialSkinManager.AddFormToManage(this);

            //默认灰+琥珀主题
            materialSkinManager.Theme = MaterialSkinManager.Themes.DARK;
            materialSkinManager.ColorScheme = new ColorScheme(
                       Primary.Grey700,
                       Primary.Grey900,
                       Primary.Grey600,
                       Accent.Amber400,
                       TextShade.WHITE);
        }
        /// <summary>
        /// 应用主题
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void themeButton_Click(object sender, EventArgs e)
        {
            switch (themeComboBox.SelectedIndex)
            {
                case 0:
                    materialSkinManager.Theme = MaterialSkinManager.Themes.DARK;
                    materialSkinManager.ColorScheme = new ColorScheme(
                               Primary.Grey700,
                               Primary.Grey900,
                               Primary.Grey600,
                               Accent.Amber400,
                               TextShade.WHITE);
                    break;
                case 1:
                    materialSkinManager.Theme = MaterialSkinManager.Themes.LIGHT;
                    materialSkinManager.ColorScheme = new ColorScheme(
                               Primary.Blue600,
                               Primary.Blue800,
                               Primary.Blue300,
                               Accent.Red100,
                               TextShade.WHITE);
                    break;
                case 2:
                    materialSkinManager.Theme = MaterialSkinManager.Themes.DARK;
                    materialSkinManager.ColorScheme = new ColorScheme(
                               Primary.Cyan700,
                               Primary.Cyan900,
                               Primary.Cyan500,
                               Accent.DeepOrange200,
                               TextShade.WHITE);
                    break;
                case 3:
                    materialSkinManager.Theme = MaterialSkinManager.Themes.DARK;
                    materialSkinManager.ColorScheme = new ColorScheme(
                                Primary.BlueGrey700,
                                Primary.BlueGrey900,
                                Primary.BlueGrey400,
                                Accent.LightBlue200,
                                TextShade.WHITE);
                    break;
                case 4:
                    materialSkinManager.Theme = MaterialSkinManager.Themes.DARK;
                    materialSkinManager.ColorScheme = new ColorScheme(
                                Primary.Green600,
                                Primary.Green700,
                                Primary.Green200,
                                Accent.Red100,
                                TextShade.WHITE);
                    break;
                case 5:
                    materialSkinManager.ColorScheme = new ColorScheme(
                                ColorTranslator.FromHtml("#596164"),
                                ColorTranslator.FromHtml("#323232"),
                                ColorTranslator.FromHtml("#304352"),
                                ColorTranslator.FromHtml("#323232"),
                                TextShade.WHITE);
                    break;
                case 6:
                    materialSkinManager.ColorScheme = new ColorScheme(
                                ColorTranslator.FromHtml("#f09819"),
                                ColorTranslator.FromHtml("#c07819"),
                                ColorTranslator.FromHtml("#f09819"),
                                ColorTranslator.FromHtml("#ff5858"),
                                TextShade.WHITE);
                    break;
                case 7:
                    materialSkinManager.ColorScheme = new ColorScheme(
                                ColorTranslator.FromHtml("#CACDCC"),
                                ColorTranslator.FromHtml("#BABDBC"),
                                ColorTranslator.FromHtml("#D8DBE2"),
                                ColorTranslator.FromHtml("#96959B"),
                                TextShade.BLACK);
                    break;
                default:
                    break;

            }
        }
    }
}
